package service

import (
	"errors"

	"github.com/google/uuid"
	"github.com/smash-llj/Nexa-server/global"
	"github.com/smash-llj/Nexa-server/models"
	"github.com/smash-llj/Nexa-server/models/request"
	"github.com/smash-llj/Nexa-server/models/response"
	"gorm.io/gorm"
)

var sessionService *SessionService

type SessionService struct {
	BaseService
}

func NewSessionService() *SessionService {
	if sessionService == nil {
		return &SessionService{
			NewBaseService(),
		}
	}
	return sessionService
}

// CreateSession 创建会话
func (s *SessionService) CreateSession(userDto request.UserFriendReq) (string, error) {
	var existingSession models.Session
	err := global.DB.Where("user_id = ? AND friend_id = ?", userDto.UserId, userDto.FriendId).First(&existingSession).Error
	if err == nil {
		return existingSession.SessionId, nil
	}
	if !errors.Is(err, gorm.ErrRecordNotFound) {
		return "", err
	}
	sessionId := uuid.New().String()
	session := models.Session{
		SessionId:   sessionId,
		UserId:      userDto.UserId,
		ToId:        userDto.FriendId,
		LastMsg:     "",
		Unread:      0,
		SessionType: 0,
		ChatType:    global.ChatTypeUser,
	}
	if err := global.DB.Create(&session).Error; err != nil {
		return "", err
	}
	return sessionId, nil
}

type rawItem struct {
	models.Session
	Username    *string
	UserAvatar  *string
	GroupName   *string
	GroupAvatar *string
}

// RecentChatSession 获取最近会话
func (s *SessionService) RecentChatSession(userID uint) ([]response.SessionItemResp, error) {
	var raws []rawItem
	query := `
		SELECT 
			s.*, 
			u.username, u.avatar as user_avatar, 
			g.name as group_name, g.avatar as group_avatar
		FROM session s
		LEFT JOIN user u ON s.chat_type = 1 AND u.id = s.to_id
		LEFT JOIN ` + "`group`" + ` g ON s.chat_type = 2 AND g.id = s.to_id
		WHERE s.user_id = ?
		ORDER BY s.is_pinned DESC, s.updated_at DESC
	`
	if err := s.Gorm.Raw(query, userID).Scan(&raws).Error; err != nil {
		return nil, err
	}

	var result []response.SessionItemResp
	for _, r := range raws {
		item := response.SessionItemResp{
			Session: r.Session,
		}
		if r.ChatType == 1 {
			item.UserInfo = response.UserSessionInfoResp{
				Name:   deref(r.Username),
				Avatar: deref(r.UserAvatar),
			}
		} else if r.ChatType == 2 {
			item.GroupInfo = response.GroupSessionInfoResp{
				Name:   deref(r.GroupName),
				Avatar: deref(r.GroupAvatar),
			}
		}
		result = append(result, item)
	}
	return result, nil
}

func deref(ptr *string) string {
	if ptr != nil {
		return *ptr
	}
	return ""
}

// PinnedSession 置顶
func (s *SessionService) PinnedSession(uid uint, sessionId string) (bool, error) {
	if err := s.BaseService.Gorm.Model(&models.Session{}).
		Where("user_id = ? AND session_id = ?", uid, sessionId).
		Update("is_pinned", gorm.Expr("CASE WHEN is_pinned = 1 THEN 0 ELSE 1 END")).Error; err != nil {
		return false, err
	}
	// 由于没有查询 is_pinned 的值，判断是否更新为 1 来返回 true 或 false
	var updatedSession models.Session
	if err := s.BaseService.Gorm.Model(&models.Session{}).
		Where("user_id = ? AND session_id = ?", uid, sessionId).
		First(&updatedSession).Error; err != nil {
		return false, err
	}
	return updatedSession.IsPinned == 1, nil
}

// UpdateSessionUnread 更新未读会话
func (s *SessionService) UpdateSessionUnread(userId uint) error {
	return s.Gorm.Model(&models.Session{}).Where("user_id = ? AND chat_type =?", userId, global.ChatNotify).Update("unread", 0).Error
}
